Suspense
Catalyst provides advanced Suspense support with intelligent SSR asset management powered by Vite. The latest version v0.0.2-canary.1
introduces smart code splitting with per-component SSR control and automatic asset categorization.
Installation
Overview
Catalyst's Suspense implementation runs on Vite's build pipeline and provides:
- Smart Code Splitting: Automatic asset categorization (essential, SSR-enabled, SSR-disabled)
- Per-Component SSR Control: Fine-grained control over server-side rendering
- Intelligent Asset Loading: Essential assets load first, non-essential assets load progressively
- Streaming SSR: Non-blocking server-side rendering with progressive enhancement
- Automatic Asset Deduplication: Prevents loading duplicate resources
The split()
Function
Use the split()
function instead of React.lazy()
for enhanced SSR compatibility and asset management:
Basic Usage
import { split } from "catalyst"
// Basic split with SSR enabled (default)
const LazyComponent = split(() => import("./LazyComponent"))
// With custom fallback
const LazyComponent = split(() => import("./LazyComponent"), {
fallback: <div>Loading component...</div>
})
// Usage in component
const Home = () => {
return (
<div>
<LazyComponent />
</div>
)
}
SSR Control
Control whether components render on the server using the ssr
flag:
// Component renders on server (default)
const ServerRenderedComponent = split(() => import("./ServerComponent"), {
ssr: true,
fallback: <div>Loading...</div>
})
// Component only renders on client
const ClientOnlyComponent = split(() => import("./ClientComponent"), {
ssr: false,
fallback: <div>Client-side only component loading...</div>
})
Real-World Examples
Dashboard with Mixed SSR Strategy:
import { split } from "catalyst"
// Critical above-the-fold content - SSR enabled
const DashboardHeader = split(() => import("./DashboardHeader"), {
ssr: true,
fallback: <div className="header-skeleton">Loading header...</div>
})
// Interactive widgets - client-side only for better performance
const InteractiveChart = split(() => import("./InteractiveChart"), {
ssr: false,
fallback: <div className="chart-skeleton">Loading chart...</div>
})
// Settings modal - lazy load when needed
const SettingsModal = split(() => import("./SettingsModal"), {
ssr: false,
fallback: null // No fallback needed for modals
})
const Dashboard = () => {
return (
<div>
<DashboardHeader />
<div className="content">
<InteractiveChart />
{/* SettingsModal loads only when state changes trigger it */}
<SettingsModal />
</div>
</div>
)
}
Asset Management
Catalyst automatically categorizes your assets based on how you use split()
:
Asset Categories
- Essential Assets: Core app functionality, entry points, shared utilities
- SSR-Enabled Assets: Components with
ssr: true
that load during server rendering - SSR-Disabled Assets: Components with
ssr: false
that load only on the client
Loading Strategy
// This happens automatically:
// 1. Essential assets load immediately
// 2. SSR-enabled assets load during server rendering
// 3. SSR-disabled assets load progressively on client
Migration from React.lazy
If you're upgrading from standard React.lazy
, here's how to migrate:
Before (React.lazy)
import React, { Suspense, lazy } from "react"
const LazyComponent = lazy(() => import("./LazyComponent"))
const App = () => (
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>
)
After (Catalyst split)
import { split } from "catalyst"
const LazyComponent = split(() => import("./LazyComponent"), {
ssr: true, // or false based on your needs
fallback: <div>Loading...</div>
})
const App = () => <LazyComponent />
Advanced Patterns
Conditional SSR Based on User Agent
const MobileOptimizedComponent = split(() => import("./MobileComponent"), {
ssr: true,
fallback: <div>Loading mobile view...</div>
})
const DesktopComponent = split(() => import("./DesktopComponent"), {
ssr: true,
fallback: <div>Loading desktop view...</div>
})
Progressive Enhancement
// Base functionality loads with SSR
const BaseArticle = split(() => import("./BaseArticle"), {
ssr: true,
fallback: <div>Loading article...</div>
})
// Enhanced features load client-side
const ArticleInteractions = split(() => import("./ArticleInteractions"), {
ssr: false,
fallback: null
})
const ArticlePage = () => (
<div>
<BaseArticle />
<ArticleInteractions />
</div>
)
Best Practices
1. SSR Strategy
- Enable SSR for above-the-fold content and SEO-critical components
- Disable SSR for highly interactive widgets, client-dependent features
- Use progressive enhancement by layering client-only features over SSR base content
2. Fallback Design
// Good: Meaningful loading states
const Component = split(() => import("./Component"), {
fallback: <div className="skeleton">Loading content...</div>
})
// Better: Match expected content structure
const Component = split(() => import("./Component"), {
fallback: (
<div className="article-skeleton">
<div className="title-skeleton" />
<div className="content-skeleton" />
</div>
)
})
3. Performance Optimization
// Group related components to reduce chunk fragmentation
const UserProfile = split(() => import("./user/UserProfile"))
const UserSettings = split(() => import("./user/UserSettings"))
const UserActivity = split(() => import("./user/UserActivity"))
Troubleshooting
Components Not Loading on Server
If your component depends on clientFetcher
data and fails on the server:
const DataDependentComponent = split(() => import("./DataComponent"), {
ssr: false, // Disable SSR for client-data dependent components
fallback: <div>Loading data-driven content...</div>
})
Asset Loading Issues
The build system automatically handles asset categorization. If you experience issues:
- Check that imports use relative paths or configured aliases
- Ensure components are properly exported as default exports
Build System Integration
Catalyst's Suspense features integrate with Vite's build system:
- Manifest Categorization Plugin: Automatically categorizes assets during build
- Cache Key Injection Plugin: Optimizes asset tracking and loading
- ChunkExtractor: Intelligently manages asset dependencies during SSR
This integration ensures optimal performance without manual configuration.